﻿using System.Collections.Generic;
using Commons.Models.OperationsContext;
using Commons.Models.TradeValues;
using Commons.Services.Locks;

namespace Commons.Services.TradeValues
{
	public class DictionaryTradeValueProcessor : ITradeValueProcessor
	{
		public IDictionary<string, ICostProcessor> CostProcessors { protected get; set; }
		public IDictionary<string, IRewardProcessor> RewardProcessors { protected get; set; }
		public ILockService LockService { protected get; set; }

		public IEnumerable<CostStatus> GetCostsStatus(ITradeValue value, IOperationContext context, int quantity)
		{
			IEnumerable<ITradeValue> tradeValues = PreProcessCost(value, context);
			foreach (ITradeValue tradeValue in tradeValues)
			{
				IEnumerable<CostStatus> costs = CostProcessors[tradeValue.Type].GetCostsStatus(tradeValue, context, quantity);
				foreach (CostStatus cost in costs)
				{
					yield return cost;
				}
			}
		}

		public IEnumerable<ITradeValue> PreProcessCost(ITradeValue value, IOperationContext context)
		{
			IEnumerable<ITradeValue> tradeValues = CostProcessors[value.Type].PreProcessCost(value, context);
			foreach (ITradeValue tradeValue in tradeValues)
			{
				if (LockService.CheckLock(value.Lock, context))
				{
					yield return tradeValue;
				}
			}
		}

		public IEnumerable<ITradeValue> ProcessCost(ITradeValue value, IOperationContext context, int quantity)
		{
			List<ITradeValue> values = new List<ITradeValue>();

			IEnumerable<ITradeValue> tradeValues = PreProcessCost(value, context);
			foreach (ITradeValue tradeValue in tradeValues)
			{
				values.AddRange(CostProcessors[tradeValue.Type].ProcessCost(tradeValue, context, quantity));
			}

			return values;
		}

		public IEnumerable<ITradeValue> PreProcessReward(ITradeValue value, IOperationContext context)
		{
			IEnumerable<ITradeValue> tradeValues = RewardProcessors[value.Type].PreProcessReward(value, context);
			foreach (ITradeValue tradeValue in tradeValues)
			{
				if (LockService.CheckLock(value.Lock, context))
				{
					 yield return tradeValue;
				}
			}
		}

		public IEnumerable<ITradeValue> ProcessReward(ITradeValue value, IOperationContext context, int quantity)
		{
			List<ITradeValue> values = new List<ITradeValue>();

			IEnumerable<ITradeValue> tradeValues = PreProcessReward(value, context);
			foreach (ITradeValue tradeValue in tradeValues)
			{
				values.AddRange(RewardProcessors[tradeValue.Type].ProcessReward(tradeValue, context, quantity));
			}

			return values;
		}
	}
}
